package com.ffcs.crmd.tsp.core.util;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.common.constant.LoggerName;

/**
 * 
 * 功能说明:通信工具类
 *
 * @author ZHONGFUHUA
 * 
 * @Date 2016年1月15日 上午11:59:54
 *
 *
 * 版本号  |   作者   |  修改时间   |   修改内容
 *
 */
public class RemotingUtil {
    
    private static Logger log = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    protected RemotingUtil() {
        
    }
    
    /**
     * 
     * 功能说明:异常简单处理化
     * 
     * @param e
     *      异常对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String exceptionSimpleDesc(Throwable e) {
        StringBuffer sb = new StringBuffer();
        if (e != null) {
            sb.append(e.toString());
            
            StackTraceElement[] stackTrace = e.getStackTrace();
            if ((stackTrace != null) && (stackTrace.length > 0)) {
                StackTraceElement elment = stackTrace[0];
                sb.append(", ");
                sb.append(elment.toString());
            }
        }
        return sb.toString();
    }
    
    /*
     * ===========================    Channel Parse   =============================
     */
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |     192.168.0.1:8080          |
     * =================================
     * </pre>
     * 
     * 功能说明:解析通道对象获取远程通信地址的ip:port
     * 
     * @param channel
     *          通道
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String parseChannelRemote(Channel channel) {
        if (null == channel) {
            return "";
        }
        return parseSocketAddress(channel.remoteAddress());
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |         FFCS-ZHONGFH          |
     * =================================
     * </pre>
     * 
     * 功能说明:解析通道对象获取远程通信地址的HostName
     * 
     * @param channel
     *          通道
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String parseChannelRemote2Name(Channel channel) {
        if (null == channel) {
            return "";
        }
        return parseSocketAddress2Name(channel.remoteAddress());
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |         192.168.0.1           |
     * =================================
     * </pre>
     * 
     * 功能说明:解析通道对象获取远程通信地址的ip
     * 
     * @param channel
     *          通道
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String parseChannelRemote2Addr(Channel channel) {
        if (null == channel) {
            return "";
        }
        return parseSocketAddress2Addr(channel.remoteAddress());
    }
    
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |             8080              |
     * =================================
     * </pre>
     * 
     * 功能说明:解析通道对象获取远程通信地址的port
     * 
     * @param channel
     *          通道
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String parseChannelRemote2Port(Channel channel) {
        if (null == channel) {
            return "";
        }
        return parseSocketAddress2Port(channel.remoteAddress());
    }
    
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |     192.168.0.1:8080          |
     * =================================
     * </pre>
     * 
     * 功能说明:解析Socket地址对象转换成ip:port
     * 
     * @param socketAddress
     *          地址对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月20日
     *
     */
    public static String parseSocketAddress(final SocketAddress socketAddress) {
        if(socketAddress != null){
            StringBuilder sb = new StringBuilder();
            InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
            sb.append(inetSocketAddress.getAddress().getHostAddress());
            sb.append(":");
            sb.append(inetSocketAddress.getPort());
            return sb.toString();
        }else{
            return "";
        }
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |         FFCS-ZHONGFH          |
     * =================================
     * </pre>
     * 
     * 功能说明:解析Socket地址对象获取HostName
     * 
     * @param addr
     *          地址对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String parseSocketAddress2Name(SocketAddress socketAddress) {
        if(socketAddress != null){
            InetSocketAddress addrs = (InetSocketAddress) socketAddress;
            if (addrs != null) {
                return addrs.getAddress().getHostName();
            }
        }
        return "";
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |         192.168.0.1           |
     * =================================
     * </pre>
     * 
     * 功能说明:解析Socket地址对象获取ip
     * 
     * @param socketAddress
     *          地址对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月20日
     *
     */
    public static String parseSocketAddress2Addr(final SocketAddress socketAddress) {
        if(socketAddress != null){
            InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
            return inetSocketAddress.getAddress().getHostAddress();
        }else{
            return "";
        }
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |            8080               |
     * =================================
     * </pre>
     * 
     * 功能说明:解析Socket地址对象获取port
     * 
     * @param socketAddress
     *          地址对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月20日
     *
     */
    public static String parseSocketAddress2Port(final SocketAddress socketAddress) {
        if(socketAddress != null){
            InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress;
            return String.valueOf(inetSocketAddress.getPort());
        }else{
            return "";
        }
    }
    
    /**
     * <pre>
     * ======= Return Example ===========
     * |  FFCS-ZHONGFH/192.168.0.1:8080 |
     * ==================================
     * </pre>
     * 
     * 功能说明:Socket地址对象转换成String类型
     * 
     * @param addr
     *          地址对象
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static String scoketAddress2String(SocketAddress socketAddress) {
        if (socketAddress != null) {
            return socketAddress.toString();
        }
        return "";
    }
    
    /**
     * <pre>
     * ======= Return Example ===========
     * |      192.168.0.1:8080          |
     * ==================================
     * </pre>
     * 
     * 功能说明:字符串地址转换成SocketAddress
     * 
     * @param socketAddress
     *          地址
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static SocketAddress string2SocketAddress(String socketAddress) {
        String[] s = socketAddress.split(":");
        InetSocketAddress isa = new InetSocketAddress(s[0], Integer.valueOf(s[1]).intValue());
        return isa;
    }

    
    /**
     * 
     * 功能说明:关闭通道
     * 
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月15日
     *
     */
    public static void closeChannel(final Channel channel) {
        channel.close().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                log.info("NETTY COMMON: one channel{} close {}",
                    channel, future.isSuccess() ? "success" : "false");
            }
        });
    }
    
    /**
     * <pre>
     * ======= Return Example ==========
     * |         192.168.0.1           |
     * =================================
     * </pre>
     * 
     * 功能说明:获取本地地址IP
     * 
     * @author ZHONGFUHUA
     *
     * @Date 2016年1月21日
     *
     */
    public static String getLocalAddress() {
        try {
            /*Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
            ArrayList<String> ipv4Result = new ArrayList<String>();
            ArrayList<String> ipv6Result = new ArrayList<String>();
            while (enumeration.hasMoreElements()) {
                final NetworkInterface networkInterface = enumeration.nextElement();
                final Enumeration<InetAddress> en = networkInterface.getInetAddresses();
                while (en.hasMoreElements()) {
                    final InetAddress address = en.nextElement();
                    if (!address.isLoopbackAddress()) {
                        if (address instanceof Inet6Address) {
                            ipv6Result.add(normalizeHostAddress(address));
                        } else {
                            ipv4Result.add(normalizeHostAddress(address));
                        }
                    }
                }
            }
            
            // prefer ipv4
            if (!ipv4Result.isEmpty()) {
                for (String ip : ipv4Result) {
                    if (ip.startsWith("127.0") || ip.startsWith("192.168")) {
                        continue;
                    }
                    return ip;
                }
                return ipv4Result.get(ipv4Result.size() - 1);
            } else if (!ipv6Result.isEmpty()) {
                return ipv6Result.get(0);
            }*/
            final InetAddress localHost = InetAddress.getLocalHost();
            return normalizeHostAddress(localHost);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        
        return null;
    }
    
    private static String normalizeHostAddress(final InetAddress localHost) {
        if (localHost instanceof Inet6Address) {
            return "[" + localHost.getHostAddress() + "]";
        } else {
            return localHost.getHostAddress();
        }
    }
    
    
    public static String getChannelId(Channel channel){
        String channelStr = channel.toString();
        return channelStr.substring(channelStr.indexOf("id: ") + 4, channelStr.indexOf(", /"));
    }
}
